package at.ac.univie.ise.generator;

import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jooq.impl.Factory;

import at.ac.univie.ise.common.Config;
import at.ac.univie.ise.schema.Tables;
import at.ac.univie.ise.schema.enums.StationhoursDay;
import at.ac.univie.ise.schema.tables.records.CityRecord;
import at.ac.univie.ise.schema.tables.records.StationRecord;
import at.ac.univie.ise.schema.tables.records.StationhoursRecord;

/**
 * Parses properties and creates entity objects from the parsed values
 * @author Chris Borckholder
 */
public class LocationGenerator {
	
	// logger
	private final Log log = LogFactory.getLog(LocationGenerator.class);
	
	private final EntityComponents ec;
	
	private List<CityRecord> cities;
	private List<StationRecord> stations;
	private List<StationhoursRecord> stationHours;
	
	public LocationGenerator(Factory f) {
		log.info(">> generating locations");
		String cityBundleName = Config.getInstance().getBundleBase() + ".cities"; 
		ResourceBundle cityBundle = ResourceBundle.getBundle(cityBundleName);
		ec = EntityComponents.getInstance();
		stationHours = new LinkedList<>();
		cities = loadCities(f,cityBundle);
		stations = generateStations(f);
		log.info("<< locations generated");
	}
	
	// read defined cities from .properties
	private List<CityRecord> loadCities(Factory create,ResourceBundle rb) {
		log.debug(">> loading cities");
		List<CityRecord> result = new LinkedList<>();
		CityRecord temp = null;
		for ( Enumeration<String> keys = rb.getKeys() ; keys.hasMoreElements() ; ) {
			String currKey = keys.nextElement();
			temp = create.newRecord(Tables.CITY);
			temp.setPostcode(Integer.parseInt(currKey));
			temp.setCityname(rb.getString(currKey));
			temp.store();
			temp.refresh();
			if ( log.isTraceEnabled() ) { log.trace("-- loaded from bundle :"+ temp.toString()); }
			result.add(temp);
		}
		log.info("<< "+ result.size() +" cities loaded");
		return result;
	}
	
	// generate defined amount of stations for each city
	private List<StationRecord> generateStations(Factory create) {
		log.debug(">> generating stations");
		List<StationRecord> result = new LinkedList<>();
		StationRecord temp = null;
		for (CityRecord city : cities) {
			for (int i = 0; i < Config.getInstance().getStationScale(); i++) {
				temp = create.newRecord(Tables.STATION);
				temp.setStationname(city.getCityname() + " " + ec.randomQualifier());
				temp.setPhonenr(ec.randomPhone());
				temp.setPostcode(city.getPostcode());
				temp.setStreet(ec.randomStreet());
				temp.store();
				temp.refresh();
				int genHours = generateHours(create,temp);
				if (log.isTraceEnabled()) { log.trace("-- generated station with "+ genHours +" hours :"+ temp.toString()); }
				result.add(temp);
			}
		}
		log.info("<< "+ result.size() +" stations generated");
		return result;
	}
	
	// generate 6 day opening hours
	private int generateHours(Factory create, StationRecord station) {
		StationhoursRecord temp = null;
		int counter = 0;
		for (StationhoursDay currDay : StationhoursDay.values()) {
			if (currDay != StationhoursDay.SUN) {
				temp = create.newRecord(Tables.STATIONHOURS);
				temp.setStationid(station.getStationid());
				temp = ec.defHours(temp, currDay);
				temp.store();				
				if (log.isTraceEnabled()) { log.trace("-- generated station hours :"+ temp.toString()); }
				stationHours.add(temp);
				counter++;
			}
		}
		return counter;
	}

	/**
	 * @return the cities
	 */
	public List<CityRecord> getCities() {
		return cities;
	}

	/**
	 * @return the stations
	 */
	public List<StationRecord> getStations() {
		return stations;
	}
}
